#include <string>
using namespace std;

#include <vector>
#include <map>

#include <sys/types.h> 
#include <sys/socket.h>
 
#include "../../../include/common/base.h"
#include "../../../include/common/collector.h"
#include "../../../include/rtdbms/rtdbFun.h"

#include "../../../include/net/ZNet.h"

#include "../../../include/fore/rtdb_fun.h"

int try_sync_rtdb(int sock);


const int					NET_TYPE_SYNC_RTDB		= 0x11;

struct SYNC_NET_HEAD
{
	int		type;
	int		count;
	int		length;
	int		check;

	SYNC_NET_HEAD()
	{
		memset(this, 0, sizeof(SYNC_NET_HEAD));
		check = -1;
	}
	int GetCheck()
	{
		int temp = type * count + length;
		return temp;
	}

	void GenCheck()
	{
		check = type * count + length;
	}

	bool IsValid()
	{
		if( GetCheck() == check ) return true;
		else return false;
	}
};

struct SYNC_RTLIB_INFO
{
	int		lib_no;
	int		lib_size;
};


bool SetRecvTimeout( int s, int mtime) 
{  
	struct timeval t;   
	  
	t.tv_sec = mtime / 1000;   
	t.tv_usec= (mtime % 1000) * 1000;   
	
    	int optlen = sizeof(timeval) ;  

	 return setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,  (char *) & t, optlen) == 0; 
}

int  SyncDbProcessThread( ZtagAcceptParam * param)
{
	if( param == NULL ) return 0;
	 
	
	int  sock = param->GetSocket(); 
 
	SetRecvTimeout( sock, 1000 * 30);   
	
	char chrClientIP[64];
	memset(chrClientIP, 0, 64); 
	param->GetClientInfo(chrClientIP); 
 
	base::my_printf("----------scada_rtdb_svr_fun --%s(%d)-------------- \n", chrClientIP, sock);
   
	while(1)
	{
		SYNC_NET_HEAD	head;
		
		if( !ZTcpSocket::Recv( sock, &head, sizeof( head ) ) ) break;
		if( !head.IsValid() ) {
			base::my_printf( "报文头校验不正确...\n" ); 
			break;
		}
		 
		int ret = 0;
		if( head.type == NET_TYPE_SYNC_RTDB )
		{
			ret = try_sync_rtdb( sock ); 
		} 

		//ZTcpSocket::SendInt( sock,  ret ); 
		if( ret <= 0 ) break;
		 		 
	}
	 
	base::my_printf("----------socket thread close ---%s(%d)------------- \n", chrClientIP, sock);
	shutdown( sock, 2 );
	close( sock );

	return 0;
}



 
int try_sync_rtdb(int sock)
{  
	int lib_count = 0;
	std::vector<int>		aryLibNo;
	  
	int lib_no = 0;
	for( lib_no = 0; lib_no < 256; lib_no++ )
	{
		if( IfUsed_libno( lib_no ) == ISUSED )
		{
			int size = GetLoad_SaveBuffSize( lib_no );
	 
			if( size > 0 )
			{
				aryLibNo.push_back( lib_no );
			}
		}
	}

	lib_count = aryLibNo.size();
	
	base::my_printf("lib_count = %d \n", lib_count);
	if( !ZTcpSocket::SendInt( sock,  lib_count ) )
	{ 
		return 0;
	}

	if( lib_count <= 0 ) return 0;
	 
	base::my_printf("beging sync rtdb.....\n");
	clock_t cb=clock();
	for( int i = 0; i < lib_count; i++ )
	{
		int lib_no = aryLibNo[i];

		//XCollector sendCol;

		SYNC_RTLIB_INFO info;
		info.lib_no = lib_no;
		info.lib_size = GetLoad_SaveBuffSize( lib_no );

		base::my_printf("lib_no = %d, lib_size = %d ", lib_no, info.lib_size );
		//sendCol.Append(&info, sizeof(SYNC_RTLIB_INFO)); 
		 
		if( !ZTcpSocket::Send( sock, &info, sizeof(SYNC_RTLIB_INFO) ) ) {
			base::my_printf("     Send SYNC_RTLIB_INFO failed  \n ");
			return 0;
		}  

		if( info.lib_size <= 0 ) continue;
		 
		char *lib_buf = new char[info.lib_size];
		 
		if( !SaveLibToMem( lib_no, lib_buf, info.lib_size ) )  {
			delete []lib_buf;
			lib_buf = NULL; 
			base::my_printf("     SaveLibToMem error \n ");
			return 0;
		}

		//sendCol.Append(lib_buf, info.lib_size);
		if( !ZTcpSocket::Send( sock, lib_buf, info.lib_size ) ) {
			delete []lib_buf;
			lib_buf = NULL;
			base::my_printf("     Send libBuf failed \n ");
			return 0;
		}  

		delete []lib_buf;
		lib_buf = NULL;
		 

		int ret_val = 0;
		int ret_len = ZTcpSocket::RecvInt( sock,  &ret_val );

		if( ret_val == 1 )
		{ 
			base::my_printf("     Send success \n ");  
		}
		else {
			base::my_printf(" recv error flag from client!! \n "); 
			return 0;
		}
	}
	clock_t ce=clock();

	base::my_printf("sync rtdb end!!!  cpu_clock=%0.6fs \n", ((double)(ce-cb))/(double)CLOCKS_PER_SEC);
 
}
